/****************************************************
	文件：GridPosition.cs
	作者：HuskyT
	邮箱：1005240602@qq.com
	日期：2021/10/18 15:51:3
	功能：Grid 位置坐标
*****************************************************/

using System;
using UnityEngine;
using System.Collections.Generic;

public struct GridPosition : IEquatable<GridPosition>, IComparable<GridPosition>
{
    /// <summary>
    /// 行  X
    /// </summary>
    public readonly int Row;

    /// <summary>
    /// 列  Y
    /// </summary>
    public readonly int Column;

    static readonly GridPosition mNone;
    static readonly GridPosition mZero;
    static readonly GridPosition mUp;
    static readonly GridPosition mDown;
    static readonly GridPosition mLeft;
    static readonly GridPosition mRight;
    static readonly GridPosition mTopLeft;
    static readonly GridPosition mTopRight;
    static readonly GridPosition mBottomLeft;
    static readonly GridPosition mBottomRight;
    static readonly List<GridPosition> mEightNeighbours;
    static readonly List<GridPosition> mFourNeighbours;

    public static GridPosition None => mNone;
    public static GridPosition Up => mUp;
    public static GridPosition Down => mDown;
    public static GridPosition Zero => mZero;
    public static GridPosition Right => mRight;
    public static GridPosition Left => mLeft;
    public static GridPosition BottomLeft => mBottomLeft;
    public static GridPosition BottomRight => mBottomRight;
    public static GridPosition TopLeft => mTopLeft;
    public static GridPosition TopRight => mTopRight;

    /// <summary>
    /// 上、右上、右、右下、下、左下、左、左上
    /// </summary>
    public static List<GridPosition> EightNeighbours => mEightNeighbours;

    /// <summary>
    /// 上、右、下、左
    /// </summary>
    public static List<GridPosition> FourNeighbours => mFourNeighbours;

    public GridPosition(int x, int y)
    {
        Row = x;
        Column = y;
    }

    static GridPosition()
    {
        mNone = new GridPosition(-1000, -1000);
        mZero = new GridPosition();
        mUp = new GridPosition(1, 0);
        mDown = new GridPosition(-1, 0);
        mLeft = new GridPosition(0, -1);
        mRight = new GridPosition(0, 1);
        mTopLeft = new GridPosition(1, -1);
        mTopRight = new GridPosition(1, 1);
        mBottomLeft = new GridPosition(-1, -1);
        mBottomRight = new GridPosition(-1, 1);
        mEightNeighbours = new List<GridPosition>
        {
            mUp,
            mTopRight,
            mRight,
            mBottomRight,
            mDown,
            mBottomLeft,
            mLeft,
            mTopLeft,
        };

        mFourNeighbours = new List<GridPosition>
        {
            mUp,
            mRight,
            mDown,
            mLeft,
        };
    }

    public bool Equals(GridPosition other)
    {
        return ((Row == other.Row) && (Column == other.Column));
    }

    public override bool Equals(object obj)
    {
        var e = false;
        if (obj is GridPosition)
            e = Equals((GridPosition) obj);
        return e;
    }

    public int CompareTo(GridPosition other)
    {
        if (Column == other.Column)
        {
            return Row.CompareTo(other.Row);
        }
        else
        {
            return Column.CompareTo(other.Column);
        }
    }

    public static bool operator ==(GridPosition a, GridPosition b)
    {
        return a.Equals(b);
    }

    public static bool operator !=(GridPosition a, GridPosition b)
    {
        if (a.Row == b.Row)
            return (a.Column != b.Column);
        return true;
    }

    public static GridPosition operator +(GridPosition a, GridPosition b)
    {
        return new GridPosition(a.Row + b.Row, a.Column + b.Column);
    }

    public static GridPosition operator -(GridPosition a, GridPosition b)
    {
        return new GridPosition(a.Row - b.Row, a.Column - b.Column);
    }

    public static GridPosition operator *(GridPosition val, int x)
    {
        return new GridPosition(val.Row * x, val.Column * x);
    }


    #region 强转类型

    public static implicit operator GridPosition(Vector2 val)
    {
        return new GridPosition(Mathf.RoundToInt(val.x), Mathf.RoundToInt(val.y));
    }

    public static implicit operator GridPosition(Vector3 val)
    {
        return new GridPosition(Mathf.RoundToInt(val.x), Mathf.RoundToInt(val.y));
    }

    public static implicit operator Vector2(GridPosition v)
    {
        return new Vector2(v.Row, v.Column);
    }
    
    public static implicit operator Vector3(GridPosition v)
    {
        return new Vector3(v.Row, v.Column);
    }

    #endregion


    public override int GetHashCode()
    {
        return (Row.GetHashCode() + Column.GetHashCode());
    }

    public override string ToString()
    {
        return $"{{x:{Row.ToString()} y:{Column.ToString()}}}";
    }

    /// <summary>
    /// 获取欧几里得距离
    /// </summary>
    public float GetEuclideanDistance(GridPosition other)
    {
        return Mathf.Sqrt((Row - other.Row) * (Row - other.Row) +
                          (Column - other.Column) * (Column - other.Column));
    }
}